package com.pp.web.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pp.common.pojo.Post;
import com.pp.common.pojo.PostTag;
import com.pp.common.pojo.User;
import com.pp.common.vo.SysResult;
import com.pp.web.model.dto.CreatePostDTO;
import com.pp.web.model.dto.UpdatePostDTO;
import com.pp.web.model.vo.PostVO;
import com.pp.web.service.IPostService;
import com.pp.web.service.IPostTagService;
import com.pp.web.service.IUserService;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;

import java.util.Map;

import static com.pp.common.util.JwtUtils.USERNAME;

@RestController
@RequestMapping("/api/post")
public class PostController extends BaseController {

    @Resource
    private IPostService postService;

    @Resource
    private IUserService userService;

    @Resource
    private IPostTagService postTagService;

    /**
     * 根据 tabName 的值分页获取帖子列表 (帖子缩略信息，不用显示帖子详情)
     * 请求方法: GET
     * 请求URL: http://localhost:8090/api/post/list
     * 请求参数: pageNo - 第几页 pageSize - 每页显示条数 tabName: latest 或 hot
     * 返回值: SysResult(postsByPages)
     */
    @GetMapping("/list")
    public SysResult getPostsByPages(
        @RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
        @RequestParam(value = "size", defaultValue = "10") Integer pageSize,
        @RequestParam(value = "tabName", defaultValue = "latest") String tabName) {
        // 由 pageNo 与 pageSize 生成 Page 对象 (MP 提供)，将 Page 对象
        Page<PostVO> postsByPages = postService.getPostsByPages(new Page<>(pageNo, pageSize), tabName);
        return SysResult.success(postsByPages);
    }

    /**
     * 发帖 (只有登录用户才能发贴)
     * 请求方法: POST
     * 请求URL: http://localhost:8090/api/post/create
     * 请求参数: post 对象 (title, content 和 tags)
     * 返回值: SysResult(post)
     */
    @PostMapping("/create")
    public SysResult createPost(
        @RequestHeader(value = USERNAME) String username,
        @Valid @RequestBody CreatePostDTO createPostDTO) {
        //  根据 username 查询对应用户
        User user = userService.getUserByUsername(username);

        // 创建帖子
        Post post = postService.createPost(createPostDTO, user);

        return SysResult.success("发布帖子成功", post);
    }

    /**
     * 根据 postId 获取帖子详情
     * 请求方法: GET
     * 请求URL: http://localhost:8090/api/post/postId
     * 请求参数: postId
     * 返回值: SysResult(responseMap): post & tags & user
     */
    @GetMapping("/{postId}")
    public SysResult getPostById(@PathVariable String postId) {
        Map<String, Object> responseMap = postService.getPostById(postId);
        return SysResult.success("获取帖子信息成功", responseMap);

    }

    /**
     * 根据 postID 更新帖子 (用户只能修改自己发的帖子，其他人的帖子无权限修改)
     * 前端有一个限制: 查看当前登录用户所发的帖子详情页才会有帖子 "编辑" 和 "删除" 按钮
     * 请求方法: PUT
     * 请求URL: http://localhost:8090/api/post/update
     * 请求参数: post 对象 (title, content 和 tags)
     *         同时 post 对象中要携带 postId 和 userId (验证帖子作者与当前登录用户是否是同一个人)
     * 返回值: SysResult(post)
     */
    @PutMapping("/update")
    public SysResult editPost(
        @RequestHeader(value = USERNAME) String username,
        @Valid @RequestBody UpdatePostDTO updatePostDTO) {
        // 更新帖子和对应的标签信息
        Post post = postService.updatePost(username, updatePostDTO);

        // 判断当前帖子是否存在
        if (ObjectUtils.isNull(post)) {
            return SysResult.fail("帖子更新失败");
        }

        // 返回更新成功信息和更新后的帖子对象
        // 修改后返回帖子信息 (此时的 post 对象中的内容已经被修改)
        return SysResult.success("帖子修改成功", post);
    }

    /**
     * 删除帖子
     */
    @DeleteMapping("/delete/{postId}")
    public SysResult deletePost(
        @RequestHeader(value = USERNAME) String username,
        @PathVariable("postId") String id) {
        // 根据 username 查询对应的 user
        User user = userService.getUserByUsername(username);

        // 根据 postId 查询对应的 post
        Post post = postService.getById(id);

        // 若帖子已经被删除，则不能重复删除
        Assert.notNull(post, "来晚一步，帖子已不存在");

        // 判断当前用户是否为当前要修改帖子的作者，若不是则提示 "非本人无权修改"
        Assert.isTrue(post.getUserId().equals(user.getId()), "无权限删除其他用户的帖子");

        // 根据 postId 删除对应的帖子 =>
        this.postService.removeById(id);

        // 同时删除 post 和 tag 的对应关系 =>
        this.postTagService.remove(
            new LambdaQueryWrapper<PostTag>().eq(PostTag::getPostId, post.getId())
        );

        // 最后维护 user 中的发帖数 postNum - 1
        int newPostNum = user.getPostNum() - 1;
        user.setPostNum(newPostNum);
        this.userService.updateById(user);

        // 提示删除成功
        return SysResult.success("帖子删除成功");
    }

}
